Return to start page
Systems/Gui/Struct Gui.j
1 library AStructSystemsGuiGui requires optional ALibraryCoreDebugMisc, AStructCoreGeneralHashTable, AStructCoreGeneralVector, ALibraryCoreGeneralPlayer, AStructCoreInterfacePlayerSelection, ALibraryCoreInterfaceCamera, ALibraryCoreInterfaceMisc, ALibraryCoreStringConversion
2
3 /// @todo Should be a static member of @struct AGui, vJass bug.
4 /// This is the generic shortcut function interface.
5 /// @param id Id of the object which belongs to the function call.
6 function interface AGuiOnPressShortcutAction takes integer id returns nothing
7
8 /// @todo Should be a static member of @struct AGui, vJass bug.
9 /// If you want to use an explicit gui action use this.
10 function interface AGuiOnPressGuiShortcutAction takes AGui gui returns nothing
11
12 /**
13 * Represents the graphical user interface which can be used by all playing players.
14 * Each player can have exactly one GUI.
15 * A GUI contains main windows which are user-defined areas on the map. That's necessary because
16 * trackables, textes and images are map-placed objects and trackables aren't removable.
17 * When you destroy an instance all docked main windows will be destroy automatically.
18 * Besides user can access a single @struct ADialog instance by using method @method dialog.
19 * There also is a simple implemention of shortcuts by creating an unit with shortcut abilities.
20 * Unfortunately a unit can only have 12 different abilities so you can't use all ASCII keys.
21 * Maybe shortcut abilities will be added dynamically (by checking which shortcuts are really necessary) in future.
22 */
23 struct AGui
24 //static constant members
25 public static constant integer shortcutArrowUpDown = 0 //these are the special shortcuts
26 public static constant integer shortcutArrowDownDown = 1
27 public static constant integer shortcutArrowLeftDown = 2
28 public static constant integer shortcutArrowRightDown = 3
29 public static constant integer shortcutArrowUpUp = 4
30 public static constant integer shortcutArrowDownUp = 5
31 public static constant integer shortcutArrowLeftUp = 6
32 public static constant integer shortcutArrowRightUp = 7
33 public static constant integer shortcutEscape = 8 //last value has to be lesser than 'a'
34 private static constant integer m_maxSpecialShortcuts = 9
35 private static constant integer m_maxMainWindows = 4 //public see above in the text macro
36 private static constant integer m_maxShortcuts = 91 //'Z' + 1
37 //static start members
38 private static integer m_shortcutHandlerUnitType
39 private static real m_shortcutHandlerX
40 private static real m_shortcutHandlerY
41 private static string m_textOk
42 private static integer m_shortcutOk
43 //static dynamic members
44 private static integer array m_shortcutAbility[thistype.m_maxShortcuts]
45 //static members
46 private static thistype array m_playerGui[12] /// bj_MAX_PLAYERS, @todo vJass bug
47 //dynamic members
48 private AGuiOnPressShortcutAction array m_onPressShortcutAction[thistype.m_maxShortcuts]
49 private integer array m_onPressShortcutActionId[thistype.m_maxShortcuts]
50 //start members
51 private player m_user
52 //members
53 private AIntegerVector m_mainWindows
54 private AMainWindow m_shownMainWindow
55 private trigger m_leaveTrigger
56 private unit m_shortcutHandler
57 private trigger m_shortcutHandleTrigger
58 private trigger array m_specialShortcutHandleTrigger[thistype.m_maxSpecialShortcuts]
59 private APlayerSelection m_playerSelection
60 private ADialog m_dialog
61
62 //! runtextmacro optional A_STRUCT_DEBUG("\"AGui\"")
63
64 //dynamic members
65
66 /// Each shortcut (including special shortcuts) can have its own action.
67 /// Additionally you can add shortcuts to widgets that they'll get the widgets action automatically.
68 public method setOnPressShortcutAction takes integer shortcut, AGuiOnPressShortcutAction onPressShortcutAction, integer id returns nothing
69 if ((shortcut >= 0) and (shortcut < thistype.m_maxSpecialShortcuts)) then
70 call this.createSpecialShortcutTrigger(shortcut)
71 endif
72 set this.m_onPressShortcutAction[shortcut] = onPressShortcutAction
73 set this.m_onPressShortcutActionId[shortcut] = id
74 endmethod
75
76 /// Convenience method.
77 /// Assigns a function to a shortcut. The function gets the AGui instance as argument.
78 public method setOnPressGuiShortcutAction takes integer shortcut, AGuiOnPressGuiShortcutAction onPressGuiShortcutAction returns nothing
79 call this.setOnPressShortcutAction(shortcut, onPressGuiShortcutAction, this)
80 endmethod
81
82 //start members
83
84 public method user takes nothing returns player
85 return this.m_user
86 endmethod
87
88 //members
89
90 public method shownMainWindow takes nothing returns AMainWindow
91 return this.m_shownMainWindow
92 endmethod
93
94 public method dialog takes nothing returns ADialog
95 return this.m_dialog
96 endmethod
97
98 //convenience methods
99
100 /// @return Returns if a dialog or main window is shown to the user.
101 public method isShown takes nothing returns boolean
102 return this.m_shownMainWindow != 0 or this.m_dialog.isDisplayed()
103 endmethod
104
105 //methods
106
107 /// Saves GUI users camera data and selection in game.
108 public method savePlayerData takes nothing returns nothing
109 call this.m_playerSelection.save()
110 endmethod
111
112 /// Loads GUI users camera data and selection from time before he has enabled the GUI.
113 public method loadPlayerData takes nothing returns nothing
114 call this.m_playerSelection.restore()
115 endmethod
116
117 public method showMainWindowByIndex takes integer index returns nothing
118 call AMainWindow(this.m_mainWindows[index]).show()
119 endmethod
120
121 public method enableShortcuts takes nothing returns nothing
122 local integer i
123 call PauseUnit(this.m_shortcutHandler, false)
124 call ShowUnit(this.m_shortcutHandler, true)
125 call SelectUnitForPlayerSingle(this.m_shortcutHandler, this.m_user)
126 call EnableTrigger(this.m_shortcutHandleTrigger)
127 call this.enableSpecialShortcutTriggers()
128 set i = 0
129 loop
130 exitwhen (i == thistype.m_maxShortcuts)
131 if (this.m_onPressShortcutActionId[i] != 0) then
132 call UnitAddAbility(this.m_shortcutHandler, thistype.m_shortcutAbility[i])
133 endif
134 set i = i + 1
135 endloop
136 endmethod
137
138 /// Resets all shortcut actions!
139 public method disableShortcuts takes nothing returns nothing
140 local integer i
141 call PauseUnit(this.m_shortcutHandler, true)
142 call ShowUnit(this.m_shortcutHandler, false)
143 call SelectUnitRemoveForPlayer(this.m_shortcutHandler, this.m_user)
144 call DisableTrigger(this.m_shortcutHandleTrigger)
145 call this.disableSpecialShortcutTriggers()
146
147 set i = 0
148 loop
149 exitwhen (i == thistype.m_maxShortcuts)
150 if (this.m_onPressShortcutActionId[i] != 0) then
151 call UnitRemoveAbility(this.m_shortcutHandler, thistype.m_shortcutAbility[i])
152 endif
153 set this.m_onPressShortcutActionId[i] = 0
154 set i = i + 1
155 endloop
156 endmethod
157
158 /// Convenience method.
159 /// Shows a simple dialog with an OK button.
160 /// @param message Displayed message.
161 public method showInfoDialog takes string message returns nothing
162 call this.m_dialog.clear()
163 call this.m_dialog.setMessage(message)
164 call this.m_dialog.addDialogButton(thistype.m_textOk, thistype.m_shortcutOk, 0)
165 call this.m_dialog.show()
166 endmethod
167
168 /**
169 * If you dock a main window it will be destroyed when the GUI will be destroyed.
170 * @return Container index.
171 * @todo Friend relation to @struct AMainWindow. In general you do not need to use this method.
172 */
173 public method dockMainWindow takes AMainWindow mainWindow returns integer
174 call this.m_mainWindows.pushBack(mainWindow)
175 return this.m_mainWindows.backIndex()
176 endmethod
177
178 /**
179 * Undocks a main window from GUI. If a main window is undocked there won't be any relationships between it and the GUI anymore.
180 * @todo Friend relation to @struct AMainWindow. In general you do not need to use this method.
181 */
182 public method undockMainWindowByIndex takes integer index returns nothing
183 call this.m_mainWindows.erase(index)
184 endmethod
185
186 /// @todo Friend relation to @struct AMainWindow, do not use!
187 public method hideShownMainWindowAndSetNew takes AMainWindow mainWindow returns nothing
188 if (this.m_shownMainWindow != 0) then
189 call this.m_shownMainWindow.hide()
190 endif
191 set this.m_shownMainWindow = mainWindow
192 endmethod
193
194 /// @todo Friend relation to @struct AMainWindow, do not use!
195 public method resetShownMainWindow takes nothing returns nothing
196 set this.m_shownMainWindow = 0
197 endmethod
198
199 private method enableSpecialShortcutTriggers takes nothing returns nothing
200 local integer i = 0
201 loop
202 exitwhen (i == thistype.m_maxSpecialShortcuts)
203 if (this.m_specialShortcutHandleTrigger[i] != null) then
204 call EnableTrigger(this.m_specialShortcutHandleTrigger[i])
205 endif
206 set i = i + 1
207 endloop
208 endmethod
209
210 private method disableSpecialShortcutTriggers takes nothing returns nothing
211 local integer i = 0
212 loop
213 exitwhen (i == thistype.m_maxSpecialShortcuts)
214 if (this.m_specialShortcutHandleTrigger[i] != null) then
215 call DisableTrigger(this.m_specialShortcutHandleTrigger[i])
216 endif
217 set i = i + 1
218 endloop
219 endmethod
220
221 private static method triggerActionPlayerLeaves takes nothing returns nothing
222 local player triggerPlayer = GetTriggerPlayer()
223 call thistype.m_playerGui[GetPlayerId(triggerPlayer)].destroy()
224 set triggerPlayer = null
225 endmethod
226
227 private method createLeaveTrigger takes nothing returns nothing
228 local event triggerEvent
229 local triggeraction triggerAction
230 set this.m_leaveTrigger = CreateTrigger()
231 set triggerEvent = TriggerRegisterPlayerEvent(this.m_leaveTrigger, this.m_user, EVENT_PLAYER_LEAVE)
232 set triggerAction = TriggerAddAction(this.m_leaveTrigger, function thistype.triggerActionPlayerLeaves)
233 set triggerEvent = null
234 set triggerAction = null
235 endmethod
236
237 private method createShortcutHandler takes nothing returns nothing
238 set this.m_shortcutHandler = CreateUnit(this.m_user, thistype.m_shortcutHandlerUnitType, thistype.m_shortcutHandlerX, thistype.m_shortcutHandlerY, 0.0)
239 call SetUnitInvulnerable(this.m_shortcutHandler, true)
240 call ShowUnit(this.m_shortcutHandler, false)
241 endmethod
242
243 private static method triggerActionOnPressShortcut takes nothing returns nothing
244 local integer i
245 local integer abilityId = GetSpellAbilityId()
246 local trigger triggeringTrigger
247 local thistype this
248 set i = 'a'
249 loop
250 exitwhen (i == thistype.m_maxShortcuts)
251 if (abilityId == thistype.m_shortcutAbility[i]) then
252 set triggeringTrigger = GetTriggeringTrigger()
253 set this = AHashTable.global().handleInteger(triggeringTrigger, "this")
254 debug if (this.m_onPressShortcutAction[i] != 0) then
255 debug call Print("Action exists")
256 debug endif
257 call this.m_onPressShortcutAction[i].execute(this.m_onPressShortcutActionId[i])
258 set triggeringTrigger = null
259 exitwhen (true)
260 endif
261 set i = i + 1
262 endloop
263 endmethod
264
265 private method createShortcutHandleTrigger takes nothing returns nothing
266 local event triggerEvent
267 local triggeraction triggerAction
268 set this.m_shortcutHandleTrigger = CreateTrigger()
269 set triggerEvent = TriggerRegisterUnitEvent(this.m_shortcutHandleTrigger, this.m_shortcutHandler, EVENT_UNIT_SPELL_CAST)
270 set triggerAction = TriggerAddAction(this.m_shortcutHandleTrigger, function thistype.triggerActionOnPressShortcut)
271 call AHashTable.global().setHandleInteger(this.m_shortcutHandleTrigger, "this", this)
272 set triggerEvent = null
273 set triggerAction = null
274 endmethod
275
276 private static method triggerActionOnPressSpecialShortcut takes nothing returns nothing
277 local trigger triggeringTrigger = GetTriggeringTrigger()
278 local thistype this = AHashTable.global().handleInteger(triggeringTrigger, "this")
279 local integer shortcut = AHashTable.global().handleInteger(triggeringTrigger, "shortcut")
280 debug call Print("SHORTCUT " + I2S(shortcut))
281 call this.m_onPressShortcutAction[shortcut].execute(this)
282 set triggeringTrigger = null
283 endmethod
284
285 /// This method won't be called in the constructor.
286 /// It is a dynamic creation.
287 private method createSpecialShortcutTrigger takes integer shortcut returns nothing
288 local event triggerEvent
289 local triggeraction triggerAction
290 //don't check if the action is 0, it can be changed dynamicly!
291 //the trigger can't be changed dynamicly
292 if (this.m_specialShortcutHandleTrigger[shortcut] == null) then
293 set this.m_specialShortcutHandleTrigger[shortcut] = CreateTrigger()
294 if (shortcut == thistype.shortcutArrowUpDown) then
295 set triggerEvent = TriggerRegisterPlayerEvent(this.m_specialShortcutHandleTrigger[shortcut], this.m_user, EVENT_PLAYER_ARROW_UP_DOWN)
296 elseif (shortcut == thistype.shortcutArrowDownDown) then
297 set triggerEvent = TriggerRegisterPlayerEvent(this.m_specialShortcutHandleTrigger[shortcut], this.m_user, EVENT_PLAYER_ARROW_DOWN_DOWN)
298 elseif (shortcut == thistype.shortcutArrowLeftDown) then
299 set triggerEvent = TriggerRegisterPlayerEvent(this.m_specialShortcutHandleTrigger[shortcut], this.m_user, EVENT_PLAYER_ARROW_LEFT_DOWN)
300 elseif (shortcut == thistype.shortcutArrowRightDown) then
301 set triggerEvent = TriggerRegisterPlayerEvent(this.m_specialShortcutHandleTrigger[shortcut], this.m_user, EVENT_PLAYER_ARROW_RIGHT_DOWN)
302 elseif (shortcut == thistype.shortcutArrowUpUp) then
303 set triggerEvent = TriggerRegisterPlayerEvent(this.m_specialShortcutHandleTrigger[shortcut], this.m_user, EVENT_PLAYER_ARROW_UP_UP)
304 elseif (shortcut == thistype.shortcutArrowDownUp) then
305 set triggerEvent = TriggerRegisterPlayerEvent(this.m_specialShortcutHandleTrigger[shortcut], this.m_user, EVENT_PLAYER_ARROW_DOWN_UP)
306 elseif (shortcut == thistype.shortcutArrowLeftUp) then
307 set triggerEvent = TriggerRegisterPlayerEvent(this.m_specialShortcutHandleTrigger[shortcut], this.m_user, EVENT_PLAYER_ARROW_LEFT_UP)
308 elseif (shortcut == thistype.shortcutArrowRightUp) then
309 set triggerEvent = TriggerRegisterPlayerEvent(this.m_specialShortcutHandleTrigger[shortcut], this.m_user, EVENT_PLAYER_ARROW_RIGHT_UP)
310 elseif (shortcut == thistype.shortcutEscape) then
311 set triggerEvent = TriggerRegisterPlayerEvent(this.m_specialShortcutHandleTrigger[shortcut], this.m_user, EVENT_PLAYER_END_CINEMATIC)
312 endif
313 set triggerAction = TriggerAddAction(this.m_specialShortcutHandleTrigger[shortcut], function thistype.triggerActionOnPressSpecialShortcut)
314 call AHashTable.global().setHandleInteger(this.m_specialShortcutHandleTrigger[shortcut], "this", this)
315 call AHashTable.global().setHandleInteger(this.m_specialShortcutHandleTrigger[shortcut], "shortcut", shortcut)
316 set triggerEvent = null
317 set triggerAction = null
318 endif
319 endmethod
320
321 /// Don't use the constructor.
322 /// Use @method getPlayerGui.
323 /// Shortcuts will be disabled first.
324 private static method create takes player user returns thistype
325 local thistype this = thistype.allocate()
326 //start members
327 set this.m_user = user
328 //members
329 set this.m_mainWindows = AIntegerVector.create()
330 set this.m_shownMainWindow = 0
331 set this.m_playerSelection = APlayerSelection.create(user)
332 set this.m_dialog = ADialog.create(user)
333
334 call this.createLeaveTrigger()
335 call this.createShortcutHandler()
336 call this.createShortcutHandleTrigger()
337 call this.disableShortcuts()
338 return this
339 endmethod
340
341 private method destroyLeaveTrigger takes nothing returns nothing
342 call DestroyTrigger(this.m_leaveTrigger)
343 set this.m_leaveTrigger = null
344 endmethod
345
346 private method removeShortcutHandler takes nothing returns nothing
347 call RemoveUnit(this.m_shortcutHandler)
348 set this.m_shortcutHandler = null
349 endmethod
350
351 private method destroyShortcutHandleTrigger takes nothing returns nothing
352 call AHashTable.global().destroyTrigger(this.m_shortcutHandleTrigger)
353 set this.m_shortcutHandleTrigger = null
354 endmethod
355
356 private method destroySpecialShortcutTriggers takes nothing returns nothing
357 local integer i = 0
358 loop
359 exitwhen (i == thistype.m_maxSpecialShortcuts)
360 if (this.m_specialShortcutHandleTrigger[i] != null) then
361 call AHashTable.global().destroyTrigger(this.m_specialShortcutHandleTrigger[i])
362 set this.m_specialShortcutHandleTrigger[i] = null
363 endif
364 set i = i + 1
365 endloop
366 endmethod
367
368 /// Will be destroyed when player leaves the game.
369 private method onDestroy takes nothing returns nothing
370 //members
371 loop
372 exitwhen (this.m_mainWindows.empty())
373 call AMainWindow(this.m_mainWindows.back()).destroy()
374 // don't pop back
375 endloop
376 call this.m_mainWindows.destroy()
377 call this.m_playerSelection.destroy()
378 call this.m_dialog.destroy()
379
380 call this.destroyLeaveTrigger()
381 call this.removeShortcutHandler()
382 call this.destroyShortcutHandleTrigger()
383 call this.destroySpecialShortcutTriggers()
384 endmethod
385
386 /**
387 * @param shortcutHandlerUnitType The unit type of the unit which is selected during the display time of the GUI. It should have all shortcut abilities.
388 * @param shortcutHandlerX The x coordinate of the shortcut handlers position.
389 * @param shortcutHandlerY The y coordinate of the shortcut handlers position.
390 * @param textOk The text which is displayed as Ok text.
391 * @param shortcutOk The shortcut which is used for the Ok text.
392 */
393 public static method init takes integer shortcutHandlerUnitType, real shortcutHandlerX, real shortcutHandlerY, string textOk, integer shortcutOk returns nothing
394 //static start members
395 set thistype.m_shortcutHandlerUnitType = shortcutHandlerUnitType
396 set thistype.m_shortcutHandlerX = shortcutHandlerX
397 set thistype.m_shortcutHandlerY = shortcutHandlerY
398 set thistype.m_textOk = textOk
399 set thistype.m_shortcutOk = shortcutOk
400 endmethod
401
402 //static dynamic members
403
404 public static method setShortcutAbility takes integer shortcutAbility, integer abilityId returns nothing
405 set thistype.m_shortcutAbility[shortcutAbility] = abilityId
406 endmethod
407
408 public static method shortcutAbility takes integer shortcutAbility returns integer
409 return thistype.m_shortcutAbility[shortcutAbility]
410 endmethod
411
412 //static methods
413
414 public static method playerGui takes player user returns thistype
415 if (thistype.m_playerGui[GetPlayerId(user)] == 0) then
416 set thistype.m_playerGui[GetPlayerId(user)] = thistype.create(user) //If you forget [GetPlayerId(user)] there is a jasshelper error
417 endif
418 return thistype.m_playerGui[GetPlayerId(user)]
419 endmethod
420
421 //static convenience methods
422
423 public static method setOnPressGuiShortcutActionForAll takes integer shortcut, AGuiOnPressGuiShortcutAction onPressGuiShortcutAction returns nothing
424 local integer i
425 local player user
426 set i = 0
427 loop
428 exitwhen (i == bj_MAX_PLAYERS)
429 set user = Player(i)
430 if (IsPlayerPlayingUser(user)) then
431 call thistype.playerGui(user).setOnPressGuiShortcutAction(shortcut, onPressGuiShortcutAction)
432 endif
433 set user = null
434 set i = i + 1
435 endloop
436 endmethod
437
438 public static method showInfoDialogToAll takes string text returns nothing
439 local integer i
440 local player user
441 set i = 0
442 loop
443 exitwhen (i == bj_MAX_PLAYERS)
444 set user = Player(i)
445 if (IsPlayerPlayingUser(user)) then
446 call thistype.playerGui(user).showInfoDialog(text)
447 endif
448 set user = null
449 set i = i + 1
450 endloop
451 endmethod
452 endstruct
453
454 endlibrary